package org.batatasframework.rawdata;

import java.util.Collection;
import java.util.List;

import javax.persistence.EntityManager;

import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.batatasframework.common.ParameterReader;
import org.batatasframework.support.AbstractSupportHandler;
import org.batatasframework.support.CatalogDefinitionCollection;
import org.batatasframework.web.RequestParameterReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import cn.bonoon.entities.AbstractRawdataImportItem;
import cn.bonoon.entities.RawdataExportEntity;
import cn.bonoon.entities.RawdataImportEntity;
import cn.bonoon.entities.RawdataImportItemStatus;
import cn.bonoon.entities.RawdataImportMaterial;
import cn.bonoon.kernel.io.DirectoryStrategy;
import cn.bonoon.kernel.io.FileInfo;
import cn.bonoon.kernel.io.FileManager;
import cn.bonoon.kernel.io.StorageFile;
import cn.bonoon.kernel.support.IOperator;

public class RawdataHandler extends AbstractSupportHandler<RawdataDefinition> {

	private @Autowired
	FileManager fileManager;

	//
	// @Override
	// protected DefinitionBuilder<RawdataDefinition> generateBuilder() {
	// return new InternalRawdataBuilder();
	// }
	//
	// private class InternalRawdataBuilder implements
	// DefinitionBuilder<RawdataDefinition>{
	// private RawdataDefinition currentDefinition;
	// private String catalog;
	//
	// @Override
	// public void addGroup(String catalog) {
	// this.catalog = catalog;
	// }
	//
	// @Override
	// public RawdataDefinition add(String key, String name/*, String vmpath*/)
	// {
	// currentDefinition = new RawdataDefinition(key, name/*, vmpath*/);
	// catalogMapped.put(catalog, key, currentDefinition);
	// return currentDefinition;
	// }
	//
	// // @Override
	// // public void add(AbstractRawdataParser<? extends
	// AbstractRawdataImportItem> parser) {
	// // parser.definition = currentDefinition;
	// // currentDefinition.parser = parser;
	// // }
	//
	// }

	// public RawdataHandler(){
	// super(new InternalRawdataBuilder());
	// }
	//
	// @Override
	// public void afterPropertiesSet() throws Exception {
	// if(null != registers){
	// for(RawdataRegister register : registers){
	// register.register(builder);
	// }
	// }
	// }

	@Override
	protected RawdataDefinition generateDefinition(String key, String name) {
		return new RawdataDefinition(key, name);
	}

	/** 把文件上传到服务器进行解析 */
	public RawdataImportResult executeUpload(String catalog,
			EntityManager entityManager, IOperator user,
			RequestParameterReader parameter) throws Exception {
		MultipartFile excel = parameter.notEmptyFile(IMPORT_EXCEL, "请上传需要解析的文档！");
		String key = parameter.notNullString(IMPORT_KEY, "文档解析器的名称不能为空！");

		CatalogDefinitionCollection<RawdataDefinition> catalogCollection = catalogMapped
				.notNull(catalog, "没有定义文档的处理解析器！");
		RawdataDefinition definition = catalogCollection.notNull(key, "没有定义文档的处理解析器！");

		log.info("开始解析导入数据" + definition + "！");
		long starttime = System.currentTimeMillis();
		String oname = excel.getOriginalFilename();
		RawdataParser parser = definition.parser;

		// 保存上传的原文件
		//这个文件是不需要传给扶贫云的
		StorageFile sfile = StorageFile.valueOf(definition.fileCatalog, excel);
		sfile.assertFile();
		sfile.setDirectoryStrategy(DirectoryStrategy.YEAR_MONTH);
		FileInfo ifile = fileManager.saveFile(sfile);

		// 创建一条导入的记录
		RawdataImportEntity rawdataImport = ifile.instance(new RawdataImportEntity());
		rawdataImport.operator(user);
		rawdataImport.setCatalog(catalogCollection.getCatalog());
		rawdataImport.setKey(key);
		rawdataImport.setTitle(definition.getName());
		rawdataImport.setName(oname);

		parser.initImport(entityManager, parameter, user, rawdataImport);

		Workbook workbook = WorkbookFactory.create(ifile.open());
		
		// 如果导入的时候有异常的，则需要生成导出的记录
		log.info("文件名：" + rawdataImport.getPath());
		List<? extends AbstractRawdataImportItem> items = parser.parseWorkbook(
				workbook, entityManager, parameter, user);

		entityManager.persist(rawdataImport);

		int total = items.size(), correctCount = 0;
		RawdataExportEntity rawdataExport = null;

		
		int sessionSize = 0;
		for (AbstractRawdataImportItem item : items) {
			item.setSubject(rawdataImport);
			if (item.getStatus() == RawdataImportItemStatus.ABNORMAL) {
				// 把解析出现异常的数据导出
				rawdataExport = rawdataExport(parser, user, parameter, entityManager, rawdataImport, rawdataExport);
				item.setExport(rawdataExport);
			} else {
				correctCount++;
			}
			/*
			 * TODO 这里需要处理的数据量比较大，可能需要进行优化处理
			 */
			entityManager.persist(item);
			//System.out.println(sessionSize);
			sessionSize++;
			// 以50条数据为一个处理单元,和配置的JDBC batch size一样
			if (sessionSize % 50 == 0) {
				// 刷新数据
				entityManager.flush();
				// 清除缓存，释放内存
				entityManager.clear();
				
			}
		}

		
		// 是否需要保存上传的附件
		Collection<MultipartFile> materials = parameter.getFiles(IMPORT_MATERIALS);
		if (!materials.isEmpty()) {
			StorageFile mfile = StorageFile.valueOf(definition.fileCatalog, materials);
			FileInfo[] files = fileManager.saveFiles(mfile);
			for (FileInfo file : files) {
				RawdataImportMaterial riMaterial = new RawdataImportMaterial();
				riMaterial.setName(file.getOriginalFilename());
				riMaterial.setPath(file.toString());
				riMaterial.setSubject(rawdataImport);

				entityManager.persist(riMaterial);
			}
		}

		long endtime = System.currentTimeMillis();

		rawdataImport.setConsuming(endtime - starttime);
		rawdataImport.setCorrectCount(correctCount);
		rawdataImport.setTotal(total);
		entityManager.merge(rawdataImport);

		log.info("导入数据[" + rawdataImport.getName() + "],共" + total + "行,耗时:"
				+ rawdataImport.getConsuming() + "毫秒");
		return new RawdataImportResult(rawdataImport, rawdataExport);
	}

	private RawdataExportEntity rawdataExport(RawdataParser parser,
			IOperator user, ParameterReader parameter,
			EntityManager entityManager, RawdataImportEntity rawdataImport,
			RawdataExportEntity rawdataExport) {
		if (null == rawdataExport) {
			rawdataExport = new RawdataExportEntity();
			rawdataExport.setSubject(rawdataImport);
			rawdataExport.setCreateAt(rawdataImport.getCreateAt());
			rawdataExport.setCreatorId(rawdataImport.getCreatorId());
			rawdataExport.setCreatorName(rawdataImport.getCreatorName());
			rawdataExport.setOwnerId(rawdataImport.getOwnerId());
			rawdataExport.setKey(rawdataImport.getKey());
			rawdataExport.setTitle(rawdataImport.getTitle());
			rawdataExport.setCatalog(rawdataImport.getCatalog());
			rawdataExport.setDownloadName("异常-" + rawdataImport.getName());
			rawdataExport.setTotal(rawdataImport.getTotal()
					- rawdataImport.getCorrectCount());
			parser.initExport(entityManager, parameter, user, rawdataExport);

			entityManager.persist(rawdataExport);
		}
		return rawdataExport;
	}

	public final static String IMPORT_KEY = "002_0";
	public final static String IMPORT_EXCEL = "002_1";
	/** 证明材料 */
	public final static String IMPORT_MATERIALS = "002_2";

	/** 把文件上传到服务器进行解析 */
	public RawdataImportResult executeUpload2(String catalog,
			EntityManager entityManager, IOperator user,
			RequestParameterReader parameter,Long projectId) throws Exception {
		MultipartFile excel = parameter.notEmptyFile(IMPORT_EXCEL, "请上传需要解析的文档！");
		String sql=" select C_ID,C_NAME,C_MD5,C_KEY from db_n3pa_funds.t_overallproject where C_ID=? and C_DELETED=0";
		Object[] obj=(Object[]) entityManager.createNativeQuery(sql).setParameter(1, projectId).getSingleResult();

		

		
		String key = String.valueOf(obj[3]);

		CatalogDefinitionCollection<RawdataDefinition> catalogCollection = catalogMapped
				.notNull(catalog, "没有定义文档的处理解析器！");
		RawdataDefinition definition = catalogCollection.notNull(key, "没有定义文档的处理解析器！");

		log.info("开始解析导入数据" + definition + "！");
		long starttime = System.currentTimeMillis();
		String oname = excel.getOriginalFilename();
		RawdataParser parser = definition.parser;

		// 保存上传的原文件
		//这个文件是不需要传给扶贫云的
		StorageFile sfile = StorageFile.valueOf(definition.fileCatalog, excel);
		sfile.assertFile();
		sfile.setDirectoryStrategy(DirectoryStrategy.YEAR_MONTH);
		FileInfo ifile = fileManager.saveFile(sfile);

		// 创建一条导入的记录
		RawdataImportEntity rawdataImport = ifile.instance(new RawdataImportEntity());
		rawdataImport.operator(user);
		rawdataImport.setCatalog(catalogCollection.getCatalog());
		rawdataImport.setKey(key);
		rawdataImport.setTitle(definition.getName());
		rawdataImport.setName(oname);
		
		rawdataImport.setOverallProjectId(((Number)obj[0]).longValue());
		rawdataImport.setProjectName(String.valueOf(obj[1]));
		rawdataImport.setMd5Code(String.valueOf(obj[2]));
		
		parser.initImport(entityManager, parameter, user, rawdataImport);

		Workbook workbook = WorkbookFactory.create(ifile.open());
		
		// 如果导入的时候有异常的，则需要生成导出的记录
		log.info("文件名：" + rawdataImport.getPath());
		List<? extends AbstractRawdataImportItem> items = parser.parseWorkbook(
				workbook, entityManager, parameter, user);

		entityManager.persist(rawdataImport);

		int total = items.size(), correctCount = 0;
		RawdataExportEntity rawdataExport = null;

		
		int sessionSize = 0;
		for (AbstractRawdataImportItem item : items) {
			item.setSubject(rawdataImport);
			if (item.getStatus() == RawdataImportItemStatus.ABNORMAL) {
				// 把解析出现异常的数据导出
				rawdataExport = rawdataExport(parser, user, parameter, entityManager, rawdataImport, rawdataExport);
				item.setExport(rawdataExport);
			} else {
				correctCount++;
			}
			/*
			 * TODO 这里需要处理的数据量比较大，可能需要进行优化处理
			 */
			entityManager.persist(item);
			//System.out.println(sessionSize);
			sessionSize++;
			// 以50条数据为一个处理单元,和配置的JDBC batch size一样
			if (sessionSize % 50 == 0) {
				// 刷新数据
				entityManager.flush();
				// 清除缓存，释放内存
				entityManager.clear();
				
			}
		}

		
		// 是否需要保存上传的附件
		Collection<MultipartFile> materials = parameter.getFiles(IMPORT_MATERIALS);
		if (!materials.isEmpty()) {
			StorageFile mfile = StorageFile.valueOf(definition.fileCatalog, materials);
			FileInfo[] files = fileManager.saveFiles(mfile);
			for (FileInfo file : files) {
				RawdataImportMaterial riMaterial = new RawdataImportMaterial();
				riMaterial.setName(file.getOriginalFilename());
				riMaterial.setPath(file.toString());
				riMaterial.setSubject(rawdataImport);

				entityManager.persist(riMaterial);
			}
		}

		long endtime = System.currentTimeMillis();

		rawdataImport.setConsuming(endtime - starttime);
		rawdataImport.setCorrectCount(correctCount);
		rawdataImport.setTotal(total);
		entityManager.merge(rawdataImport);

		log.info("导入数据[" + rawdataImport.getName() + "],共" + total + "行,耗时:"
				+ rawdataImport.getConsuming() + "毫秒");
		return new RawdataImportResult(rawdataImport, rawdataExport);
	}

}
